#include <string>
#include <vector>
#include <stdlib.h>
#include <string.h>
#include "util.hpp"
// 编写网络协议
namespace Protocol
{
#define SEP " "
#define SEP_LEN strlen(SEP)
#define HEAD "\r\n"
#define HEAD_LEN strlen(HEAD)
    std::string AddHead(const std::string &str)
    {
        std::cout << "添加报头前: " << str << std::endl;
        std::string ret;
        ret += std::to_string(str.size());
        ret += HEAD;
        ret += str;
        ret += HEAD;
        std::cout << "添加报头后: " << ret << std::endl;
        return ret;
    }
    // 从socket读取数据,保存到inbuffer中,并解析出数据报放到package中
    int Readpackage(int socket, std::string *inbuffer, std::string *package)
    {
        cout << "读取数据前:" << *inbuffer << endl;
        Log log_;
        char buffer[1024] = {0};
        int n = recv(socket, buffer, sizeof(buffer), 0);

        *inbuffer += buffer; // 保存读到的数据
        cout << "读取数据中:" << endl
             << *inbuffer;

        if (n < 0) // 出错后返回
        {
            return -1;
        }
        // 截取一个数据报 "5\r\t"x + y"\r\t
        int pos = inbuffer->find(HEAD, 0);
        if (pos == -1)
        {
            return -1;
        }
        // 截取的是记录着有效载荷长的字符串
        std::string Size = inbuffer->substr(0, pos);
        int lensize = atoi(Size.c_str()); // 有效载荷长度
        int packagelen = lensize + 2 * HEAD_LEN + Size.size();
        if ((*inbuffer).size() < packagelen) // 读取的数据不够一个数据报
            return 0;
        *package = inbuffer->substr(pos + HEAD_LEN, lensize);
        inbuffer->erase(0, packagelen);
        cout << "读取数据后:" << endl
             << *inbuffer;
        return lensize;
    }
    // 移除报头 "5\r\t"x + y"\r\t
    std::string RemoveHead(const std::string str, int len)
    {
        cout << "移除报头前:" << str << endl;
        string ret = str.substr(str.size() - len, len);

        cout << "移除报头后:" << ret << endl;
        return ret;
    }
    //"10 + 10"
    class Request
    {
    public:
        Request()
        {
            ;
        }
        Request(int x, int y, char op)
            : x_(x), y_(y), op_(op)
        {
            ;
        }
        // class -> string 序列化
        bool serialize(std::string *res)
        {
            *res += std::to_string(x_);
            *res += SEP;
            *res += op_;
            *res += SEP;
            *res += std::to_string(y_);
            cout<<"Request序列化后: "<<*res<<endl;
            return true;
        }
        // string -> class "x + y" 反序列化
        bool Deserialize(const std::string &res)
        {
            std::vector<std::string> vs;
            util::StringSplit(res, SEP, &vs);
            if (vs.size() != 3)
                return false;
            x_ = atoi(vs[0].c_str());
            if (vs[1].size() != 1)
                return false;
            op_ = vs[1][0];
            y_ = atoi(vs[2].c_str());
           Print();
        }
        void Print()
        {
            cout<<"x_: "<<x_<<endl;
            cout<<"y_: "<<y_<<endl;
        }
        ~Request()
        {
            ;
        }
        int x_;
        int y_;
        char op_;
    };

    class Response
    {
    public:
        Response()
        {
            ;
        }
        Response(int result, int exitcode)
            : result_(result), exitcode_(exitcode)
        {
            ;
        }
        // class -> string
        bool serialize(std::string *msg)
        {
            *msg += std::to_string(result_);
            *msg += SEP;
            *msg += std::to_string(exitcode_);
            return true;
        }
        // string -> class
        bool Deserialize(const std::string &res)
        {
            std::vector<std::string> vs;
            util::StringSplit(res, SEP, &vs);
            if (vs.size() != 2)
                return false;
            result_ = atoi(vs[0].c_str());
            exitcode_ = atoi(vs[1].c_str());
            return true;
            Print();
        }
        void Print()
        {
            cout<<"result_: "<<result_<<endl;
            cout<<"exitcode_: "<<exitcode_<<endl;
        }
        ~Response()
        {
            ;
        }
        int result_;
        int exitcode_;
    };
};